/*************************************************************************
 *
 *    Used with ICCARM and AARM.
 *
 *    (c) Copyright IAR Systems 2010
 *
 *    File name   : main.c
 *    Description : main module
 *
 *    History :
 *    1. Date        : January 15, 2010
 *       Author      : Stanimir Bonev
 *       Description : Create
 *
 *  This example project shows how to use the IAR Embedded Workbench for ARM
 * to develop code for the IAR KSK-i.MX25 board. It shows basic use
 * of I/O, system initialization (PLL, MAX, AIPI, EMI, MMU, AITC), timers
 * and UART1 (CN3). The example return echo on every received characher, LED0
 * indicate framing error, LED1 indicate overrun erro and LED2 indicate brake.
 *
 *  Terminal settings:
 *   Communication speed: 115200 bps
 *   Number of data bits:    8
 *   Number of stop bits:    1
 *   Parity:              none
 *
 *  Set the jumpers and the switches regarding the IAR KSK-i.MX25 User's Manual
 *
 *    $Revision: 39070 $
 *
 **************************************************************************/
#include <intrinsics.h>
#include "board.h"
#include "arm_comm.h"
#include "drv_asic.h"
#include "arm926ej_cp15_drv.h"
#include "ttbl.h"
#include "drv_i2c1.h"
#include "drv_MC34704.h"

static volatile Int32U Gpt1Counter;
Int8U  Buffer[100];

Int32U Rx_Position = 0;
Int8U  Rx_Buffer[100];

Int32U Push;
Int32U Pop;
volatile Boolean FramingError;
volatile Boolean OverrunError;
volatile Boolean BreakDetect;

static Int32U secFlag = 0;


/*************************************************************************
 * Function Name: GPT1_Handler
 * Parameters: none
 *
 * Return: none
 *
 * Description: GPT1 interrupt handler
 *
 *************************************************************************/
static void toggle_LEDC6()
{
  if ( Gpt1Counter&0x1 ){
      LEDC6_ON();
  }else{
      LEDC6_OFF();           
  }  
}

static
void GPT1_Handler(void)
{
  // Clear interrupt flag
  GPT1SR_bit.OF1 = 1;
  ++Gpt1Counter; 
  secFlag = 1;
}

/*************************************************************************
 * Function Name: UART1_Handler
 * Parameters: none
 *
 * Return: none
 *
 * Description: UART interrupt handler
 *
 *************************************************************************/
static
void UART1_Handler(void)
{
Int32U count;
  // Errors
  if(USR2_1_bit.BRCD)
  {
    // break
    USR2_1_bit.BRCD = 1;
    BreakDetect = TRUE;
  }
  if(USR1_1_bit.FRAMERR)
  {
    // framing error
    USR1_1_bit.FRAMERR = 1;
    FramingError = TRUE;
  }
  if(USR2_1_bit.ORE)
  {
    // overrun error
    USR2_1_bit.ORE = 0;
    OverrunError = TRUE;
  }
  // receiver part
  if(USR1_1_bit.AGTIM)
  {
    USR1_1_bit.AGTIM = 1;
    // Pop remaing data from RX FIFO
    do
    {
      Buffer[Push++] = URXD_1;
      if(Push == sizeof(Buffer)/sizeof(Buffer[0]))
      {
        Push = 0;
      }
    }
    while(USR2_1_bit.RDR);
  }

  while(USR1_1_bit.RRDY)
  {
    Buffer[Push++] = URXD_1;
    if(Push == sizeof(Buffer)/sizeof(Buffer[0]))
    {
      Push = 0;
    }
  }
  // transmitter part
  if(   UCR1_1_bit.TRDYEN
     && USR1_1_bit.TRDY)
  {
    for(count = 30; count; count--)
    {
      UTXD_1 = Buffer[Pop++];
      if (Pop == sizeof(Buffer)/sizeof(Buffer[0]))
      {
        Pop = 0;
      }
      if(Pop == Push)
      {
        Pop = Push = 0;
        UCR1_1_bit.TRDYEN = 0;    // Transmitter Ready Interrupt disable
        break;
      }
    }
  }
}


static void UART2_Handler(void)
{
  Int32U count;
  // Errors
  if(USR2_2_bit.BRCD){ // break
    USR2_2_bit.BRCD = 1;
    BreakDetect = TRUE;
  }
  if(USR1_2_bit.FRAMERR){ // framing error
    USR1_2_bit.FRAMERR = 1;
    FramingError = TRUE;
  }
  if(USR2_2_bit.ORE){  // overrun error
    USR2_2_bit.ORE = 0;
    OverrunError = TRUE;
  }  
  
  toggle_LEDC6();  
}

void handle_Rx_msg(char val)
{
  Rx_Buffer[Rx_Position] = val; 
  toggle_LEDC6();  
}

static void UART4_Handler(void)
{
  Int32U count;
  char temp_char;
  // Errors
  if(USR2_4_bit.BRCD){ // break
    USR2_4_bit.BRCD = 1;
    BreakDetect = TRUE;
  }
  if(USR1_4_bit.FRAMERR){ // framing error
    USR1_4_bit.FRAMERR = 1;
    FramingError = TRUE;
  }
  if(USR2_4_bit.ORE){  // overrun error
    USR2_4_bit.ORE = 0;
    OverrunError = TRUE;
  }  
  
  //toggle_LEDC6();
  ///*
  // receiver part
  if(USR1_4_bit.AGTIM)
  {
 //   toggle_LEDC6();    
    USR1_4_bit.AGTIM = 1;
    // Pop remaing data from RX FIFO
    do
    {
      temp_char = URXD_4;
      handle_Rx_msg(temp_char); 
    }
    while(USR2_4_bit.RDR);
  }
  while(USR1_4_bit.RRDY) {
 //     toggle_LEDC6();    
      temp_char = URXD_4;
      handle_Rx_msg(temp_char); 
  } 
  //*/
}

int uart4_putc(char a)
{
  if(UCR1_4_bit.TRDYEN && USR1_4_bit.TRDY) {        
    UTXD_4 = a;
    return 1;
  }else{
    return 0;    
  }
}
int uart4_putstr(char* aPtr, int size)
{
  int count = 0;
  char temp;
  
  while ( count < size ){
    temp = *aPtr++;
    count++;
    if(UCR1_4_bit.TRDYEN && USR1_4_bit.TRDY) {        
      UTXD_4 = temp;
    }
  }

}

void test_uart2()
{
  // UART Init
  // Enable UART1 clock
  CGCR0_bit.ipg_per_uart  = 1;
  CGCR2_bit.ipg_clk_uart2 = 1;

  UCR2_2_bit.SRST = 0;
  while(!UCR2_2_bit.SRST);
  UCR1_2_bit.RRDYEN = 1;    // Receiver Ready Interrupt Enable
  UCR2_2_bit.RXEN = 1;      // receiver enable
  UCR2_2_bit.TXEN = 1;      // Transmitter enable
  UCR2_2_bit.ATEN = 1;      // Aging Timer Enable
  UCR2_2_bit.WS = 1;        // 8 bits word
  UCR2_2_bit.STPB = 0;      // 1 stop bit
  UCR2_2_bit.PREN = 0;      // no parity
  UCR2_2_bit.IRTS = 1;      // flowcontrol disable
  UCR3_2_bit.RXDMUXSEL = 1; // RXD Muxed Input Selected
  UCR3_2_bit.FRAERREN = 1;  // enable framing error
  UCR4_2_bit.OREN = 1;      // enable overrun error
  UCR4_2_bit.BKEN = 1;      // enable break condition detection interrupt
  UFCR_2_bit.RXTL = 1;      // RxFIFO has 1 character
  UFCR_2_bit.TXTL = 2;      // TxFIFO has 2 or fewer characters
  UFCR_2_bit.RFDIV = 5;     // Divide input clock by 1
  UFCR_2_bit.DCEDTE = 0;    // Select data communication equipment (DCE)

  ONEMS_2 =  HCLK /((PCDR3_bit.PERDIV15+1) + 1000);
  UBIR_2 = 1152-1;
  UBMR_2 = 41562-1;
  USR1_2 = 0xFFFFFFFF;      // clear pending interrupts
  USR2_2 = 0xFFFFFFFF;      // clear pending interrupts
  
//  UTS_4_bit.LOOP = 1; // LOOPBACK Test

  //UART 2
  IOMUXC_SW_MUX_CTL_PAD_UART2_RXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_TXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_RTS_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_CTS_bit.MUX_MODE = ALT0_MUX_MODE;  
  // Init UART1 interrupt
  ASIC_SetupIntr(UART2_Handler,FALSE,INT_UART2,1);
  ASIC_EnableIntSource(INT_UART2);

  UCR1_2_bit.UARTEN = 1;    // enable UART
  Push = 0;
  Pop = 0;

  // Enable interrupts
  ASIC_EnableIRQ();
  ASIC_EnableFIQ();
  __enable_interrupt();  
  
  while(1){    
   if (secFlag == 1){
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55;
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55; 
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55; 
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55;    
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55;
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55; 
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55; 
      if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
        UTXD_2 = 0x55;       
      secFlag = 0;
    }     
 }
}

/*************************************************************************
 * Function Name: main
 * Parameters: none
 *
 * Return: none
 *
 * Description:
 *
 *************************************************************************/
int main(void)
{
  // Init MMU
  CP15_Mmu(FALSE);            // Disable MMU
  // Privileged permissions  User permissions AP
  // Read-only               Read-only        0
  CP15_SysProt(FALSE);
  CP15_RomProt(TRUE);
  CP15_InitMmuTtb(TtSB,TtTB); // Build L1 and L2 Translation tables
  CP15_SetTtb(L1Table);       // Set base address of the L1 Translation table
  CP15_SetDomain( (DomainManager << 2*1) | (DomainClient << 0)); // Set domains
  CP15_Mmu(TRUE);             // Enable MMU
  CP15_Cache(TRUE);           // Enable ICache,DCache

  // LEDs Init
//  IOMUXC_SW_MUX_CTL_PAD_A14_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A15_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A16_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A17_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A18_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A19_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A20_bit.MUX_MODE = ALT5_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_A21_bit.MUX_MODE = ALT5_MUX_MODE;
//  LED_PORT |= LED_MASK;
//  LED_DIR  |= LED_MASK;
  
  IOMUXC_SW_MUX_CTL_PAD_FEC_MDIO_bit.MUX_MODE = ALT5_MUX_MODE;
 // IOMUXC_SW_MUX_CTL_CSI_D5_bit.MUX_MODE = ALT5_MUX_MODE;
 
  LEDC_PORT |= LEDC_MASK;
  LEDC_DIR  |= LEDC_MASK;      

  // Init AITC
  ASIC_Init();

  // Init GTIM
  Gpt1Counter = 0;
  // Enable GPT1 clock
  CGCR0_bit.ipg_per_gpt  = 1;
  CGCR1_bit.ipg_clk_gpt1 = 1;

  // Disable timer
  GPT1CR = 0;
  // Disable interrupt
  GPT1IR_bit.OF1IE = 0;
  // Reset Timer1
  GPT1CR_bit.SWR = 1;
  while(GPT1CR_bit.SWR);
  // ipg_clk_highfreq - PERCLK5
  GPT1CR_bit.CLKSRC= 2;
  // reset counters
  GPT1CR_bit.ENMOD = 1;
  // Restart counter
  GPT1CR_bit.FRR = 0;

  // Init the Timer's period
  GPT1PR_bit.PRESCALER = 0;
  GPT1OCR1 = HCLK / ((PCDR1_bit.PERDIV5+1) * GPT1_TICK_PER_SEC);
  // Init GPT1 interrupt
  ASIC_SetupIntr(GPT1_Handler,FALSE,INT_GPT1,1);
  ASIC_EnableIntSource(INT_GPT1);
  // Enable GPT1
  GPT1CR_bit.EN = 1;
  // Enable Oput compare 1 interrupt
  GPT1IR_bit.OF1IE = 1;

  I2C1_Init();
  
//  test_uart2();

  // UART Init
  // Enable UART1 clock
  CGCR0_bit.ipg_per_uart  = 1;
  CGCR2_bit.ipg_clk_uart2 = 1;

  UCR2_2_bit.SRST = 0;
  while(!UCR2_2_bit.SRST);
  UCR1_2_bit.RRDYEN = 1;    // Receiver Ready Interrupt Enable
  UCR2_2_bit.RXEN = 1;      // receiver enable
  UCR2_2_bit.TXEN = 1;      // Transmitter enable
  UCR2_2_bit.ATEN = 1;      // Aging Timer Enable
  UCR2_2_bit.WS = 1;        // 8 bits word
  UCR2_2_bit.STPB = 0;      // 1 stop bit
  UCR2_2_bit.PREN = 0;      // no parity
  UCR2_2_bit.IRTS = 1;      // flowcontrol disable
  UCR3_2_bit.RXDMUXSEL = 1; // RXD Muxed Input Selected
  UCR3_2_bit.FRAERREN = 1;  // enable framing error
  UCR4_2_bit.OREN = 1;      // enable overrun error
  UCR4_2_bit.BKEN = 1;      // enable break condition detection interrupt
  UFCR_2_bit.RXTL = 1;      // RxFIFO has 1 character
  UFCR_2_bit.TXTL = 2;      // TxFIFO has 2 or fewer characters
  UFCR_2_bit.RFDIV = 5;     // Divide input clock by 1
  UFCR_2_bit.DCEDTE = 0;    // Select data communication equipment (DCE)

  ONEMS_2 =  HCLK /((PCDR3_bit.PERDIV15+1) + 1000);
  UBIR_2 = 1152-1;
  UBMR_2 = 41562-1;
  USR1_2 = 0xFFFFFFFF;      // clear pending interrupts
  USR2_2 = 0xFFFFFFFF;      // clear pending interrupts
  
//  UTS_4_bit.LOOP = 1; // LOOPBACK Test
  //UART4
//  IOMUXC_SW_MUX_CTL_PAD_KPP_COL0_bit.MUX_MODE = ALT1_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_KPP_COL1_bit.MUX_MODE = ALT1_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_KPP_COL2_bit.MUX_MODE = ALT1_MUX_MODE;
//  IOMUXC_SW_MUX_CTL_PAD_KPP_COL3_bit.MUX_MODE = ALT1_MUX_MODE;
  //UART 2
  IOMUXC_SW_MUX_CTL_PAD_UART2_RXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_TXD_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_RTS_bit.MUX_MODE = ALT0_MUX_MODE;
  IOMUXC_SW_MUX_CTL_PAD_UART2_CTS_bit.MUX_MODE = ALT0_MUX_MODE;  
  // Init UART1 interrupt
  ASIC_SetupIntr(UART2_Handler,FALSE,INT_UART2,1);
  ASIC_EnableIntSource(INT_UART2);

  UCR1_2_bit.UARTEN = 1;    // enable UART
  Push = 0;
  Pop = 0;

  // Enable interrupts
  ASIC_EnableIRQ();
  ASIC_EnableFIQ();
  __enable_interrupt();

  // MC34704 init
//  MC34704_Init();
  
  Gpt1Counter= 0;
 /* 
  Buffer[0] = 0x55;
  Buffer[1] = 0xaa;
  Buffer[2] = 0x55;
  Buffer[3] = 0xff;
  Buffer[4] = 0x00;
  Buffer[5] = 0x55;  
  Buffer[6] = 0xaa;  
  Buffer[7] = 0xff; 
  Buffer[8] = 0x00;  
  Buffer[9] = 0x55;   
  //*/
//  uart4_putc(0x41); // A
//  uart4_putc(0x54); // T
//  uart4_putc(0x0D); // <CR> 
  
  while(1){
        // transmitter part
    if (secFlag == 1){
        for(int count = 0; count < 0xffff; count ++) {
 //         uart4_putc(Buffer[count]); 
       //   if(UCR1_2_bit.TRDYEN && USR1_2_bit.TRDY)         
            UTXD_2 = 0x55;
        }
//        uart4_putstr(Buffer, 10);
        secFlag = 0;
   }
  };
  {
    if( Push && !Pop)
    {
      // begin transmit
      UCR1_4_bit.TRDYEN = 1;    // Transmitter Ready Interrupt Enable
    }
    if(Gpt1Counter >= 8)
    {
      Gpt1Counter = 0;
      if(FramingError)
      {
        FramingError = FALSE;
      }
      if(OverrunError)
      {
        OverrunError = FALSE;
      }
      if(BreakDetect)
      {
        BreakDetect = FALSE;
      }
    }
  }
}
